package vg.services.graph_view_manager.realization.graph_view.smart_graph_view;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;

import vg.services.data_base_manager.data.graph.Graph;
import vg.services.graph_view_manager.interfaces.graph_view.AGraphView;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphAlgorithms;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphInformation;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphObservable;
import vg.services.graph_view_manager.interfaces.graph_view.IGraphSettings;
import vg.services.graph_view_manager.interfaces.graph_view.IHighLevelGraphEditor;
import vg.services.graph_view_manager.interfaces.graph_view.ILowLevelEditGraphMethods;
import vg.services.graph_view_manager.interfaces.tab.ATab;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.interfaces.ISGVPatch;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVGraphAlgorithms;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVGraphSettings;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVGraphView4Patching;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVTopScreen;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVGraphInformation;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVGraphObservable;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVHighLevelGraphEditor;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVLowLevelGraphEditor;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.SGVPatchManager;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.patches.MergePatch;
import vg.services.graph_view_manager.realization.graph_view.smart_graph_view.realization.patches.NewGraphPatch;
import vg.services.main_manager.MainManager;

/**
 * This class is wrapper to jgraphx library.
 * @author tzolotuhin
 */

public class SmartGraphView extends AGraphView {	
	// Mutex
	private final Object generalMutex = new Object();

	// Main components
	private SGVGraphView4Patching sgv_graph_view4patching;
	private SGVTopScreen sgv_top_screen;
	private SGVPatchManager sgv_patch_manager;
	private String title;
	
	private SGVGraphInformation sgv_graph_information;
	private SGVHighLevelGraphEditor sgv_high_level_graph_editor;
	private SGVLowLevelGraphEditor sgv_low_level_graph_editor;
	private SGVGraphObservable sgv_graph_observable; 
	private SGVGraphSettings sgv_graph_settings;
	private SGVGraphAlgorithms sgv_graph_algorithms;

//=============================================================================
//-----------------Constructors------------------------------------------------
	public SmartGraphView(Graph graph) {
		super(ATab.DEF_GRAPH_VIEW_TAB_TYPE);
		init();
		
		title = MainManager.model.generateTitle4SubGraph(graph);
		if (title == null)
			title = "Unknown";

		// new graph actions
		sgv_patch_manager.addPatch(new NewGraphPatch(graph));
		sgv_high_level_graph_editor.executeCurrentLayout();
	}
	
	public SmartGraphView(AGraphView graphView, Graph graph) {
		this(graph);
		
		if (graphView != null && graphView instanceof SmartGraphView) {
			sgv_patch_manager.addPatch(new MergePatch((SmartGraphView)graphView, this, ((SmartGraphView) graphView).sgv_graph_view4patching, sgv_graph_view4patching, graph));
		}
	}
	
	public void addPatch(ISGVPatch patch) {
		sgv_patch_manager.addPatch(patch);
	}
//=============================================================================
//-----------------IMPLEMENTATION OF AGraphView--------------------------------
	@Override
	public JComponent getView() {
		return sgv_top_screen.getView();
	}
	
	@Override
	public String getTabTitle() {
		synchronized (generalMutex) {
			return title;			
		}
	}
	
	@Override
	public void setTabTitle(String title) {
		synchronized (generalMutex) {
			this.title = title;
		}
	}
	
	@Override
	public IGraphInformation getGraphInformation() {
		return sgv_graph_information;
	}
	
	@Override
	public IGraphObservable getGraphObservable() {
		return sgv_graph_observable;
	}

	@Override
	public IHighLevelGraphEditor getHighLevelGraphEditor() {
		return sgv_high_level_graph_editor;
	}
	
	@Override
	public ILowLevelEditGraphMethods getLowLevelGraphEditor() {
		return sgv_low_level_graph_editor;
	}
	
	@Override
	public IGraphSettings getGraphSettings() {
		return sgv_graph_settings;
	}
	
	@Override
	public IGraphAlgorithms getGraphAlgorithms() {
		return sgv_graph_algorithms;
	}
	
//=============================================================================
//-----------------PRIVATE METHODS--------------------------------------------- 
	private void init() {
		// initialize components
		if (SwingUtilities.isEventDispatchThread()) {
			sgv_graph_view4patching = new SGVGraphView4Patching(this);
		} else {
			try {
				SwingUtilities.invokeAndWait(new Runnable() {
					@Override
					public void run() {
						sgv_graph_view4patching = new SGVGraphView4Patching(SmartGraphView.this);						
					}
				});
			} catch (Exception ex) {
				MainManager.log.printException(ex);
			}
		}
		sgv_top_screen = new SGVTopScreen(sgv_graph_view4patching);
		sgv_patch_manager = new SGVPatchManager(sgv_top_screen);
		
		// initialize services for graph view
		sgv_graph_information = new SGVGraphInformation(sgv_patch_manager);
		sgv_high_level_graph_editor = new SGVHighLevelGraphEditor(sgv_patch_manager);
		sgv_low_level_graph_editor = new SGVLowLevelGraphEditor(sgv_patch_manager);
		sgv_graph_observable = new SGVGraphObservable(sgv_patch_manager);
		sgv_graph_settings = new SGVGraphSettings(sgv_patch_manager);
		sgv_graph_algorithms = new SGVGraphAlgorithms(sgv_patch_manager);		
	}
}
